package de.karlNet.sambamanager.ldapController.commands.macros;

import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.naming.NamingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Controller;

import de.karlNet.sambamanager.ldapController.LdapMemberOfTree;
import de.karlNet.sambamanager.ldapController.OriginalLdapTree;
import de.karlNet.sambamanager.ldapModel.ITypeCheckerCallback;
import de.karlNet.sambamanager.ldapModel.LdapGroup;
import de.karlNet.sambamanager.ldapModel.LdapObject;
import de.karlNet.sambamanager.ldapModel.LdapUser;
import de.karlNet.sambamanager.ldapModel.dto.LdapGroupCreationDTO;
import de.karlNet.sambamanager.ldapModel.dto.LdapUserCreationDTO;

@Controller
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ExtractGroupMacro {
	@Autowired
	private CreateGroupMacro createGroupMacro;
	@Autowired
	private OriginalLdapTree originalLdapTree;
	@Autowired
	private ModifyUserMacro modifyUserMacro;
	@Autowired
	private LdapMemberOfTree ldapMemberOfTree;

	private void createGroup(LdapUser ldapUser, LdapGroup extractedGroup) {
		LdapGroupCreationDTO dto = new LdapGroupCreationDTO();
		dto.setLdapGroup(extractedGroup);
		for (String groupToExtract : ldapUser.getMemberOf()) {
			LdapGroup ldapGroup = (LdapGroup) this.originalLdapTree
					.getObject(groupToExtract);
			dto.getMembers().add(ldapGroup);
		}
		this.createGroupMacro.createGroup(dto);
	}

	private void modifyUser(LdapUser ldapUser, LdapGroup extractedGroup)
			throws UnsupportedEncodingException, NamingException {
		LdapUserCreationDTO userCreationDTO = new LdapUserCreationDTO();
		userCreationDTO.setLdapUser(ldapUser);
		userCreationDTO.setMemberships(new LdapGroup[] { extractedGroup });
		this.modifyUserMacro.updateUser(userCreationDTO);
	}

	public void extractGroupFromUser(LdapUser ldapUser, LdapGroup extractedGroup)
			throws UnsupportedEncodingException, NamingException {
		this.createGroup(ldapUser, extractedGroup);
		this.modifyUser(ldapUser, extractedGroup);
	}

	public void extractGroupFromUserAndModifyAllUsers(final LdapUser ldapUser,
			final LdapGroup extractedGroup) {
		this.createGroup(ldapUser, extractedGroup);
		List<LdapObject> candidates = this.ldapMemberOfTree.getRootNodes();
		for (LdapObject ldapObject : candidates) {
			ldapObject.isType(new ITypeCheckerCallback() {
				@Override
				public void isUser(LdapUser ldapUserToCompare) {
					if (ldapUserToCompare.getMemberOf().containsAll(
							ldapUser.getMemberOf())
							&& ldapUser.getMemberOf().containsAll(
									ldapUserToCompare.getMemberOf())) {
						try {
							modifyUser(ldapUserToCompare, extractedGroup);
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();
						} catch (NamingException e) {
							e.printStackTrace();
						}
					}
				}

			});
		}
	}

}
